package com.nineclock.approve.service.impl;
import com.google.common.collect.Lists;
import com.nineclock.approve.dto.ApproveDefinitionBaseDataDto;

import java.util.Date;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nineclock.approve.dto.*;
import com.nineclock.approve.mapper.ApproveDefinitionMapper;
import com.nineclock.approve.pojo.ApproveDefinition;
import com.nineclock.approve.service.ActivitiService;
import com.nineclock.approve.service.ApproveDefinitionService;
import com.nineclock.approve.utils.ApproveExtendsUtils;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.filter.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.common.utils.UUIDUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
@Transactional
public class ApproveDefinitionServiceImpl implements ApproveDefinitionService {

    @Autowired
    private ApproveDefinitionMapper approveDefinitionMapper;

    @Autowired
    private ActivitiService activitiService;

    @Override
    public List<ApproveGroupDefinitionDto> queryApproveGroupDefinition() {

        // 获取当前登录用户所属企业id
        Long companyId = CurrentUserHolder.get().getCompanyId();

        LambdaQueryWrapper<ApproveDefinition> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ApproveDefinition::getCompanyId, companyId);
        wrapper.eq(ApproveDefinition::getIsValid, 1);

        List<ApproveDefinition> approveDefinitionList = approveDefinitionMapper.selectList(wrapper);

        if (!CollectionUtils.isEmpty(approveDefinitionList)) {

            List<ApproveGroupDefinitionDto> resultList = new ArrayList<>();

            // 根据所属类型分组
            Map<String, List<ApproveDefinition>> map = approveDefinitionList.stream().collect(Collectors.groupingBy(ApproveDefinition::getGroupType));


            for (String groupType : map.keySet()) {

                ApproveGroupDefinitionDto approveGroupDefinitionDto = new ApproveGroupDefinitionDto();
                approveGroupDefinitionDto.setGroupType(groupType);
                approveGroupDefinitionDto.setDefinitionList(map.get(groupType));

                resultList.add(approveGroupDefinitionDto);

            }

            return resultList;
        }

        return null;
    }

    @Override
    public void saveApproveDefinition(ApproveDefinitionDto approveDefinitionDto) {
        // 参数校验
        if (approveDefinitionDto == null || approveDefinitionDto.getBaseData() == null ||
                CollectionUtils.isEmpty(approveDefinitionDto.getTableData()) ||
                StringUtils.isEmpty(approveDefinitionDto.getFlowData())
        ) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        ApproveDefinitionBaseDataDto baseData = approveDefinitionDto.getBaseData(); // 基础信息

        if (StringUtils.isEmpty(baseData.getId())) { // 新增

            ApproveDefinition approveDefinition = BeanHelper.copyProperties(baseData, ApproveDefinition.class);
            approveDefinition.setCompanyId(CurrentUserHolder.get().getCompanyId().toString());
            approveDefinition.setIsValid("1");
            approveDefinition.setTableName("flow" + UUIDUtils.getUUID()); // 表单名，暂时用不到
            approveDefinition.setCreateTime(new Date());
            approveDefinition.setUpdateTime(new Date());
            approveDefinition.setDataFrom("1");  // 1-自定义流程，2-根据模板创建

            // 调用公共方法，设置流程定义
            setApproveDefinitionInfo(approveDefinitionDto, baseData, approveDefinition);

            approveDefinitionMapper.insert(approveDefinition);

            // 动态构建BPMN模型，部署到Activiti
            activitiService.deployProcessToActiviti(approveDefinition);


        } else { // 修改

            // 根据id查询流程定义信息
            ApproveDefinition approveDefinition = approveDefinitionMapper.selectById(baseData.getId());
            approveDefinition = BeanHelper.copyProperties(baseData, ApproveDefinition.class);

            approveDefinition.setTableName("flow" + UUIDUtils.getUUID()); // 表单名，暂时用不到
            approveDefinition.setUpdateTime(new Date());

            // 调用公共方法，设置流程定义
            setApproveDefinitionInfo(approveDefinitionDto, baseData, approveDefinition);

            approveDefinitionMapper.updateById(approveDefinition);

            // 删除已有的流程定义
            activitiService.deleteProcessDefinition(approveDefinition);

            // 添加新的流程定义
            activitiService.deployProcessToActiviti(approveDefinition);
        }

    }

    /**
     * 保存流程定义公共方法
     * @param approveDefinitionDto
     * @param baseData
     * @param approveDefinition
     */
    private void setApproveDefinitionInfo(ApproveDefinitionDto approveDefinitionDto, ApproveDefinitionBaseDataDto baseData, ApproveDefinition approveDefinition) {
        // 设置谁可以发起审批
        List<AllowUserObjDto> allowUserObjDtoList = baseData.getAllowUserJson();
        if (!CollectionUtils.isEmpty(allowUserObjDtoList)) {
            approveDefinition.setAllowUserJson(JSON.toJSONString(allowUserObjDtoList));
        }

        // 设置表单数据
        List<ApproveDefinitionTableDataDto> tableData = approveDefinitionDto.getTableData();
        approveDefinition.setFormJson(JSON.toJSONString(tableData));

        // 设置colums，前端需要额外增加一个fieldKey
        List<ColumnObjDto> columnObjDtos = ApproveExtendsUtils.getClolumnListWithFieldKey(approveDefinitionDto);
        approveDefinition.setColumns(JSON.toJSONString(columnObjDtos));


        // 设置流程数据，需要额外增加一个nodekey
        String flowData = approveDefinitionDto.getFlowData();
        // 解析json字符串，得到一个jsonArray
        JSONArray jsonArray = JSON.parseArray(flowData);
        ApproveExtendsUtils.expandParamWithNodeKey(jsonArray);
        approveDefinition.setFlowJson(JSON.toJSONString(jsonArray));
    }

    @Override
    public ApproveDefinitionDto queryById(String id) {
        ApproveDefinition approveDefinition = approveDefinitionMapper.selectById(id);

        // 定义DTO
        ApproveDefinitionDto approveDefinitionDto = new ApproveDefinitionDto();

        // 设置基本信息
        ApproveDefinitionBaseDataDto baseData = BeanHelper.copyProperties(approveDefinition, ApproveDefinitionBaseDataDto.class);
        approveDefinitionDto.setBaseData(baseData);

        // 设置表单数据
        String formJson = approveDefinition.getFormJson();
        List<ApproveDefinitionTableDataDto> tableData = JSON.parseArray(formJson, ApproveDefinitionTableDataDto.class);
        approveDefinitionDto.setTableData(tableData);

        // 设置流程数据
        approveDefinitionDto.setFlowData(approveDefinition.getFlowJson());

        return approveDefinitionDto;
    }
}
